api: disallow a guest to change his role to member/manager#7740
api: disallow a guest to change his role to member/manager#7740BacLuc merged 1 commit intoecamp:develfrom
Conversation
|
@CodeRabbit review this pr |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chainI'll help you review this PR! Let me gather information about the changes first. 🏁 Script executed: Length of output: 16736 @BacLuc Great work on implementing this security fix! This PR effectively prevents privilege escalation by guests. Here's my comprehensive review: ✅ Security ImplementationThe core security logic is solid:
🔧 Code Quality Issues
private readonly CampRoleVoter $campRoleVoter, // ← Remove this
throw new HttpException(403, 'Guests cannot elevate their role to member or manager');
public function onBeforeRoleChange(CampCollaboration $data, CampCollaboration $previous): CampCollaboration {
$currentUser = $this->security->getUser();
$isOwnCollaboration = $data->user->getId() === $currentUser->getId();
// Only check role escalation for own collaborations
if (!$isOwnCollaboration) {
return $data;
}
$previousRole = $previous->role;
$canElevateRole = in_array($previousRole, [CampCollaboration::ROLE_MANAGER, CampCollaboration::ROLE_MEMBER], true);
if (!$canElevateRole) {
throw new HttpException(403, 'Guests cannot elevate their role to member or manager');
}
return $data;
}📋 Testing CoverageExcellent test coverage! The tests cover:
Minor improvement - some test method names could be more descriptive: // Instead of:
testPatchOwnCampCollaborationToMemberIsRejectedForGuest()
// Consider:
testGuestCannotElevateOwnRoleToMember()🏗️ Architecture NotesThe PropertyChangeListener pattern is well-implemented. The changes to support 1-2 parameters in Your note about potentially moving this to 🚀 Overall AssessmentThis is a solid security improvement with good test coverage. The main issues are minor code quality improvements (unused dependency, clearer error messages) rather than functional problems. Recommendation: ✅ Approve after addressing the unused dependency. 🐰 |
Fix it in CampCollaborationUpdateProcessor for now, because that's the only place this is a problem now. Maybe we should later fix this in the CampRoleVoter. It only is a problem when the own campCollaboration is changed.
7af3f32 to
af31650
Compare
|
@CodeRabbit i fixed some issues |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: Length of output: 16753 @BacLuc Excellent work on the updates! I can see you've addressed several key issues from my previous review: ✅ Fixed Issues
💡 Minor Remaining OpportunitiesThe security implementation is solid and functional! A couple of minor refinements could still be considered:
🎯 Overall AssessmentThis is a significant improvement! The expanded test coverage is particularly impressive and gives great confidence in the security fix. The main functional issues have been resolved. Status: ✅ Ready for merge - the security implementation is solid and well-tested. Great work on addressing the feedback so thoroughly! 🚀 |
| if ($data->user->getId() !== $user->getId()) { | ||
| return $data; | ||
| } | ||
| if (in_array($previous->role, [CampCollaboration::ROLE_MANAGER, CampCollaboration::ROLE_MEMBER], true)) { |
There was a problem hiding this comment.
Members also aren't allowed to change their own role, or are they? Doesn't the same apply for members?
And is there some camp collaboration state which has the same flaw?
There was a problem hiding this comment.
They are with the current implementation.
A similar issue: #3440
https://github.com/ecamp/ecamp3/blob/devel/api/src/Entity/Camp.php#L39
https://github.com/ecamp/ecamp3/blob/devel/api/src/Entity/CampCollaboration.php#L44
I did not wan't to change that too in the same PR.
There was a problem hiding this comment.
So, this PR is only concerned with restricting guests, not members. I'm fine with that, as long as we don't keep the equivalent flaw for members around for long.
| } | ||
| if (self::hasOneParameter($beforeAction)) { | ||
| throw new \InvalidArgumentException('afterAction must have exactly one parameter'); | ||
| if (self::hasAtMostTwoParameter($beforeAction)) { |
There was a problem hiding this comment.
The naming of these parameter checking functions seems backwards to me. It's not returning whether the callback has at most two parameters, it's returning whether it has more than two or less than one
There was a problem hiding this comment.
Yes, i also ran into it when developing.
But as far as i remember php-cs-fixer did not like !self::hasOneParameter because the method would only be used with negation.
Should i change this in this PR?
e.g.
validationFailsFoOneParamter
validationFailsForAtMostTwoParamter
?
There was a problem hiding this comment.
Up to you. Since you had to rewrite the PropertyChangeListener for this feature anyways, I'd have no problem accepting this refactoring in the same PR. But we can also do it later to get things moving here.
There was a problem hiding this comment.
It's okay for me to merge now, to fix this one case. However I'd like to have a more general fix in the voter some time. The voter could load the original data of $subject before the change from the db and perform the permission check on that old version of the object. Or, to gain access to the request context, like AssertAllowTransitionsValidator, the Voter could get a RequestStack object and then get the old version of the subject via $this->requestStack->getCurrentRequest()->attributes->get('previous_data') (but maybe make sure the subject is really equivalent to the entity being mutated, by checking iri equality)
|
Fix it in CampCollaborationUpdateProcessor for now, because that's the only place this is a problem now.
Maybe we should later fix this in the CampRoleVoter. It only is a problem when the own campCollaboration is changed.